﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace ImageRenderControl
{
    /// <summary>
    /// 表示一个基于控制点插补生成的平滑曲线
    /// </summary>
    public class InterpolatedCurveShape : Shape, IDisposable
    {
        // 窗口坐标系中的控制点
        public List<PointF> controlPoints;

        // 图像坐标系中的控制点
        public List<PointF> imageControlPoints;
        private Pen pen;
        private float tension = 0.5f; // 曲线张力参数
        private int selectedPointIndex = -1;
        private PointF _rotationCenter; // 旋转中心点（起始点）

        // 构造函数
        public InterpolatedCurveShape(List<PointF> points, Pen pen = null)
        {
            if (points.Count < 2)
            {
                throw new ArgumentException("至少需要两个控制点才能创建曲线");
            }

            controlPoints = new List<PointF>(points);
            this.pen = pen ?? new Pen(Color.Red, 2f);

            // 初始化图像坐标点（默认与窗口坐标相同）
            imageControlPoints = new List<PointF>(points);

            // 设置旋转中心为第一个点（起始点）
            _rotationCenter = points.Count > 0 ? points[0] : new PointF(0, 0);

            // 初始化旋转矩阵
            UpdateRotationMatrix();
        }

        // 构造函数 - 使用窗口坐标，并转换为图像坐标
        public InterpolatedCurveShape(List<PointF> points, Func<PointF, PointF> overlayToImageTransform, Pen pen = null)
            : this(points, pen)
        {
            // 如果提供了坐标转换函数，立即更新图像坐标
            if (overlayToImageTransform != null)
            {
                UpdateImageCoordinates(overlayToImageTransform);
            }
        }

        // 构造函数 - 同时使用窗口坐标和图像坐标
        public InterpolatedCurveShape(List<PointF> overlayPoints, List<PointF> imagePoints, Pen pen = null)
        {
            if (overlayPoints == null || overlayPoints.Count < 2)
            {
                throw new ArgumentException("至少需要两个控制点才能创建曲线");
            }

            if (imagePoints == null || imagePoints.Count != overlayPoints.Count)
            {
                throw new ArgumentException("窗口坐标点和图像坐标点数量必须相同");
            }

            controlPoints = new List<PointF>(overlayPoints);
            imageControlPoints = new List<PointF>(imagePoints);
            this.pen = pen ?? new Pen(Color.Red, 2f);

            // 设置旋转中心为第一个点（起始点）
            _rotationCenter = overlayPoints.Count > 0 ? overlayPoints[0] : new PointF(0, 0);

            // 初始化旋转矩阵
            UpdateRotationMatrix();
        }

        // 属性
        public List<PointF> ControlPoints => controlPoints;
        public List<PointF> ImageControlPoints => imageControlPoints;

        public Pen Pen => pen;

        public float Tension
        {
            get => tension;
            set => tension = Math.Max(0, Math.Min(1, value));
        }

        public int SelectedPointIndex
        {
            get => selectedPointIndex;
            set => selectedPointIndex = value;
        }

        // 更新旋转矩阵
        private void UpdateRotationMatrix()
        {
            RotationMatrix.Reset();

            // 以第一个点（起始点）为中心进行旋转
            if (controlPoints.Count > 0)
            {
                PointF pivot = _rotationCenter;
                RotationMatrix.Translate(pivot.X, pivot.Y);
                RotationMatrix.Rotate(RotationAngle);
                RotationMatrix.Translate(-pivot.X, -pivot.Y);
            }
        }

        // 曲线绘制方法
        public override void Draw(Graphics g)
        {
            if (controlPoints.Count < 2) return;

            // 保存当前图形状态
            GraphicsState state = g.Save();

            try
            {
                // 应用旋转变换
                g.MultiplyTransform(RotationMatrix);

                // 根据选中状态决定使用的笔
                // 问题可能出在这里，确保根据IsSelected属性切换颜色
                using (Pen drawPen = new Pen(IsSelected ? Color.Blue : Color.Red, pen.Width))
                {
                    // 绘制曲线
                    if (controlPoints.Count >= 3)
                    {
                        g.DrawCurve(drawPen, controlPoints.ToArray(), tension);
                    }
                    else if (controlPoints.Count == 2)
                    {
                        // 只有两个点时绘制直线
                        g.DrawLine(drawPen, controlPoints[0], controlPoints[1]);
                    }
                }

                // 如果被选中，绘制控制点
                if (IsSelected)
                {
                    DrawControlPoints(g);
                }
            }
            finally
            {
                // 恢复图形状态
                g.Restore(state);
            }
        }

        // 绘制控制点
        private void DrawControlPoints(Graphics g)
        {
            // 使用蓝色笔绘制控制点
            using (Brush handleBrush = new SolidBrush(Color.Blue))
            using (Pen handlePen = new Pen(Color.Blue, 1))
            {
                foreach (var point in controlPoints)
                {
                    // 绘制控制点
                    float handleSize = 6;
                    g.FillRectangle(handleBrush,
                        point.X - handleSize / 2,
                        point.Y - handleSize / 2,
                        handleSize, handleSize);
                }
            }
        }

        // 检查点是否在曲线上
        public override bool Contains(Point point)
        {
            if (controlPoints.Count < 2) return false;

            // 将点转换到曲线坐标系
            PointF[] pts = new PointF[] { new PointF(point.X, point.Y) };
            using (Matrix inverse = RotationMatrix.Clone())
            {
                inverse.Invert();
                inverse.TransformPoints(pts);
            }
            PointF transformedPoint = pts[0];

            // 检查是否点击在控制点上
            for (int i = 0; i < controlPoints.Count; i++)
            {
                PointF controlPoint = controlPoints[i];
                if (Math.Abs(transformedPoint.X - controlPoint.X) <= 6 &&
                    Math.Abs(transformedPoint.Y - controlPoint.Y) <= 6)
                {
                    selectedPointIndex = i;
                    return true;
                }
            }

            // 检查是否点击在曲线上
            using (GraphicsPath path = new GraphicsPath())
            {
                if (controlPoints.Count >= 3)
                {
                    path.AddCurve(controlPoints.ToArray(), tension);
                }
                else if (controlPoints.Count == 2)
                {
                    path.AddLine(controlPoints[0], controlPoints[1]);
                }

                using (Pen testPen = new Pen(Color.Black, 6))
                {
                    return path.IsOutlineVisible(transformedPoint, testPen);
                }
            }
        }

        // 移动曲线，同时更新窗口坐标和图像坐标
        public override void Move(float dx, float dy, Func<PointF, PointF> overlayToImageTransform)
        {
            // 更新旋转中心点
            _rotationCenter = new PointF(_rotationCenter.X + dx, _rotationCenter.Y + dy);

            // 更新窗口坐标系中的控制点
            for (int i = 0; i < controlPoints.Count; i++)
            {
                controlPoints[i] = new PointF(
                    controlPoints[i].X + dx,
                    controlPoints[i].Y + dy
                );
            }

            // 更新旋转矩阵
            UpdateRotationMatrix();

            // 如果提供了坐标转换函数，更新图像坐标
            if (overlayToImageTransform != null)
            {
                UpdateImageCoordinates(overlayToImageTransform);
            }
        }

        // 更新图像坐标点
        public override void UpdateImageCoordinates(Func<PointF, PointF> overlayToImageTransform)
        {
            if (overlayToImageTransform == null) return;

            // 确保图像控制点列表长度与窗口控制点列表相同
            if (imageControlPoints.Count != controlPoints.Count)
            {
                imageControlPoints.Clear();
                for (int i = 0; i < controlPoints.Count; i++)
                {
                    imageControlPoints.Add(new PointF());
                }
            }

            // 计算旋转后的窗口坐标点
            List<PointF> rotatedPoints = GetRotatedPoints();

            // 将窗口坐标转换为图像坐标
            for (int i = 0; i < rotatedPoints.Count; i++)
            {
                imageControlPoints[i] = overlayToImageTransform(rotatedPoints[i]);
            }
        }

        // 获取应用旋转变换后的控制点
        private List<PointF> GetRotatedPoints()
        {
            List<PointF> rotatedPoints = new List<PointF>(controlPoints.Count);

            if (RotationAngle == 0)
            {
                // 如果没有旋转，直接返回原控制点
                return new List<PointF>(controlPoints);
            }

            // 应用旋转变换到控制点
            PointF[] points = controlPoints.ToArray();
            Matrix rotationMatrix = RotationMatrix.Clone();
            rotationMatrix.TransformPoints(points);

            for (int i = 0; i < points.Length; i++)
            {
                rotatedPoints.Add(points[i]);
            }

            return rotatedPoints;
        }

        // 根据调整大小操作更新曲线
        public void UpdateFromResizing(int pointIndex, Point newLocation, Func<PointF, PointF> overlayToImageTransform = null)
        {
            if (pointIndex < 0 || pointIndex >= controlPoints.Count) return;

            // 将新位置转换到曲线坐标系（考虑旋转）
            PointF[] pts = new PointF[] { new PointF(newLocation.X, newLocation.Y) };
            using (Matrix inverse = RotationMatrix.Clone())
            {
                inverse.Invert();
                inverse.TransformPoints(pts);
            }
            PointF transformedPoint = pts[0];

            // 更新指定控制点
            controlPoints[pointIndex] = transformedPoint;

            // 如果移动的是第一个点（起始点），则更新旋转中心
            if (pointIndex == 0)
            {
                _rotationCenter = transformedPoint;
                UpdateRotationMatrix();
            }

            // 如果提供了坐标转换函数，更新图像坐标
            if (overlayToImageTransform != null)
            {
                UpdateImageCoordinates(overlayToImageTransform);
            }
        }

        // 获取控制点中心
        public Dictionary<int, PointF> GetControlPointCenters()
        {
            Dictionary<int, PointF> handles = new Dictionary<int, PointF>();

            // 获取旋转后的控制点
            List<PointF> rotatedPoints = GetRotatedPoints();

            for (int i = 0; i < rotatedPoints.Count; i++)
            {
                handles.Add(i, rotatedPoints[i]);
            }

            return handles;
        }

        // 调整曲线大小
        public override void AdjustSize(float factor, Func<PointF, PointF> overlayToImageTransform)
        {
            if (controlPoints.Count < 2) return;

            // 计算中心点（使用第一个点作为基准点）
            PointF center = controlPoints[0];

            // 从第一个点按比例调整所有控制点
            for (int i = 1; i < controlPoints.Count; i++)
            {
                controlPoints[i] = new PointF(
                    center.X + (controlPoints[i].X - center.X) * factor,
                    center.Y + (controlPoints[i].Y - center.Y) * factor
                );
            }

            // 如果提供了坐标转换函数，更新图像坐标
            if (overlayToImageTransform != null)
            {
                UpdateImageCoordinates(overlayToImageTransform);
            }
        }

        // 调整曲线旋转
        public override void AdjustRotation(float angleDelta, Func<PointF, PointF> overlayToImageTransform)
        {
            RotationAngle += angleDelta;

            // 规范化角度到0-360范围
            while (RotationAngle < 0) RotationAngle += 360;
            while (RotationAngle >= 360) RotationAngle -= 360;

            // 更新旋转矩阵
            UpdateRotationMatrix();

            // 如果提供了坐标转换函数，更新图像坐标
            if (overlayToImageTransform != null)
            {
                UpdateImageCoordinates(overlayToImageTransform);
            }
        }

        // 删除控制点
        public bool RemoveControlPoint(int index, Func<PointF, PointF> overlayToImageTransform = null)
        {
            if (index < 0 || index >= controlPoints.Count)
                return false;

            // 确保至少保留两个控制点
            if (controlPoints.Count <= 2)
                return false;

            // 如果删除的是第一个点（起始点），则需要更新旋转中心
            if (index == 0 && controlPoints.Count > 1)
            {
                _rotationCenter = controlPoints[1];
                UpdateRotationMatrix();
            }

            controlPoints.RemoveAt(index);

            // 同步删除图像坐标点
            if (index < imageControlPoints.Count)
            {
                imageControlPoints.RemoveAt(index);
            }

            selectedPointIndex = -1; // 重置选择

            // 如果提供了坐标转换函数，更新图像坐标
            if (overlayToImageTransform != null)
            {
                UpdateImageCoordinates(overlayToImageTransform);
            }

            return true;
        }

        // 计算曲线中心点
        private PointF CalculateCenter()
        {
            if (controlPoints.Count == 0)
                return new PointF(0, 0);

            float sumX = 0, sumY = 0;
            foreach (var point in controlPoints)
            {
                sumX += point.X;
                sumY += point.Y;
            }
            return new PointF(sumX / controlPoints.Count, sumY / controlPoints.Count);
        }

        // 删除控制点
        public bool RemoveControlPoint(int index)
        {
            if (index < 0 || index >= controlPoints.Count)
                return false;

            // 确保至少保留两个控制点
            if (controlPoints.Count <= 2)
                return false;

            controlPoints.RemoveAt(index);
            selectedPointIndex = -1; // 重置选择
            return true;
        }

        // 插入新控制点
        public bool InsertControlPoint(int index, PointF point, Func<PointF, PointF> overlayToImageTransform = null)
        {
            if (index < 0 || index > controlPoints.Count)
                return false;

            // 将点转换到曲线坐标系（考虑旋转）
            PointF[] pts = new PointF[] { point };
            using (Matrix inverse = RotationMatrix.Clone())
            {
                inverse.Invert();
                inverse.TransformPoints(pts);
            }
            PointF transformedPoint = pts[0];

            controlPoints.Insert(index, transformedPoint);

            // 如果插入的是第一个点（起始点），则更新旋转中心
            if (index == 0)
            {
                _rotationCenter = transformedPoint;
                UpdateRotationMatrix();
            }

            selectedPointIndex = index; // 设置新插入点为选中

            // 如果提供了坐标转换函数，更新图像坐标
            if (overlayToImageTransform != null)
            {
                UpdateImageCoordinates(overlayToImageTransform);
            }
            else if (index < imageControlPoints.Count)
            {
                // 否则在相同位置插入一个默认图像坐标点
                imageControlPoints.Insert(index, point);
            }

            return true;
        }

        // 获取图像坐标系中的所有控制点
        public PointF[] GetImageCoordinatePoints()
        {
            return imageControlPoints.ToArray();
        }

        // 获取窗口坐标系中的所有控制点
        public PointF[] GetOverlayCoordinatePoints()
        {
            return GetRotatedPoints().ToArray();
        }

        // 添加更新控制点的方法，同时更新窗口坐标和图像坐标
        public void UpdateControlPoints(List<PointF> newPoints, Func<PointF, PointF> overlayToImageTransform = null)
        {
            if (newPoints == null || newPoints.Count < 2)
            {
                throw new ArgumentException("至少需要两个控制点才能创建曲线");
            }

            controlPoints.Clear();
            controlPoints.AddRange(newPoints);

            // 更新旋转中心为第一个点
            if (newPoints.Count > 0)
            {
                _rotationCenter = newPoints[0];
            }

            // 更新旋转矩阵
            UpdateRotationMatrix();

            // 如果提供了坐标转换函数，更新图像坐标
            if (overlayToImageTransform != null)
            {
                UpdateImageCoordinates(overlayToImageTransform);
            }
            else
            {
                // 否则清除并重新添加图像坐标点（与窗口坐标点相同）
                imageControlPoints.Clear();
                imageControlPoints.AddRange(newPoints);
            }
        }


        // 释放资源
        public void Dispose()
        {
            pen?.Dispose();
        }

    }
}